package com.lianjinsu.shop.service.impl;

import com.alibaba.fastjson2.JSON;
import com.lianjinsu.shop.controller.dto.OrdersDto;
import com.lianjinsu.shop.controller.dto.OrdersDto.ExtendShop;
import com.lianjinsu.shop.entity.Orders;
import com.lianjinsu.shop.entity.OrdersRef;
import com.lianjinsu.shop.entity.Shop;
import com.lianjinsu.shop.entity.enums.OrderStatus;
import com.lianjinsu.shop.repository.dao.OrdersDao;
import com.lianjinsu.shop.repository.dao.OrdersRefDao;
import com.lianjinsu.shop.repository.dao.ShopDao;
import com.lianjinsu.shop.service.OrdersService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class OrdersServiceImpl implements OrdersService {

    private final OrdersDao ordersDao;

    private final OrdersRefDao ordersRefDao;

    private final ShopDao shopDao;

    @Override
    public Orders getById(String tradeSn) {
        Orders orders = ordersDao.getById(tradeSn);
        List<OrdersRef> ordersRefList = ordersRefDao.ordersRefList(orders.getTradeSn());
        orders.setOrdersRefList(ordersRefList);
        return orders;
    }

    @Override
    public boolean deleteById(String tradeSn) {
        ordersRefDao.removeByTradeSn(tradeSn);
        return ordersDao.removeById(tradeSn);
    }

    @Override
    public boolean update(Orders orders) {
        return orders.updateById();
    }

    @Override
    public List<Orders> selectByUser(String openId) {
        List<Orders> ordersList = ordersDao.selectByUser(openId);
        extracted(ordersList);
        return ordersList;
    }

    @Override
    public Map<String, Object> generateOrder(OrdersDto ordersDto) {
        LocalDateTime now = LocalDateTime.now();
        String tradeSn = "T-" + now.getNano();
        List<OrdersRef> ordersRefList = ordersDto.getShopIds().stream().map(e -> {
            OrdersRef ordersRef = new OrdersRef();
            ordersRef.setTradeSn(tradeSn);
            ordersRef.setShopId(e.getShopId());
            ordersRef.setNum(e.getNum());
            ordersRef.setCreateTime(now);
            return ordersRef;
        }).collect(Collectors.toList());
        ordersRefDao.saveBatchNew(ordersRefList);

        Orders orders = new Orders();
        orders.setOpenid(ordersDto.getOpenid());
        orders.setTotalPrice(orders.getTotalPrice());
        orders.setDiscount(ordersDto.getDiscount());
        orders.setCreateTime(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        orders.setTradeSn(tradeSn);
        orders.setGoodsInfoList(JSON.toJSONString(ordersDto.getShopIds()));
        orders.setStatus(OrderStatus.UNPAID);
        orders.insertOrUpdate();
        return Collections.singletonMap("tradeSn", tradeSn);
    }

    @Override
    public List<Orders> ordersList(int status) {
        OrderStatus orderStatus = OrderStatus.ofStatus(status);
        List<Orders> ordersList = ordersDao.selectByStatus(orderStatus);
        extracted(ordersList);
        return ordersList;
    }

    private void extracted(List<Orders> ordersList) {
        List<String> tradeSnList = ordersList.stream().map(Orders::getTradeSn).collect(Collectors.toList());
        List<OrdersRef> ordersRefList = ordersRefDao.ordersRefList(tradeSnList);
        Map<String, List<OrdersRef>> tradeSnListMap = ordersRefList.stream()
            .collect(Collectors.groupingBy(OrdersRef::getTradeSn));
        ordersList.forEach(e -> e.setOrdersRefList(tradeSnListMap.get(e.getTradeSn())));
    }

    @Override
    public int cancelOrder(String tradeSn) {
        Orders orders = ordersDao.getById(tradeSn);
        String goodsInfoList = orders.getGoodsInfoList();
        List<ExtendShop> extendShopList = JSON.parseArray(goodsInfoList, ExtendShop.class);
        extendShopList.forEach(e -> {
            Shop shop = shopDao.getById(e.getShopId());
            shop.setSale(shop.getSale() - e.getNum());
            shop.setStock(shop.getStock() + e.getNum());
            shopDao.updateById(shop);
        });

        orders.setStatus(OrderStatus.CANCEL);
        return ordersDao.updateStatus(orders);
    }

    @Override
    public List<Orders> waitPayOrdersList() {
        List<Orders> ordersList = ordersDao.selectByStatus(OrderStatus.UNPAID);
        extracted(ordersList);
        return ordersList;
    }
}
